/**
 * 包含一些会用到的工具方法
 */
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include"Log.hpp"
#include<atomic>
#include<sys/time.h>
#include<boost/algorithm/string.hpp>
namespace ns_Detail
{
    // 定义日志宏常量简化传参
#define LOG(level, format, ...)                                                  \
    do                                                                           \
    {                                                                            \
        LogMessage(__FILE__, __LINE__, Save_File, level, format, ##__VA_ARGS__); \
    } while (0)
//"__FILE__" 能自动获取当前文件名字 ; "__LINE__" 能自动获取当前代码所在的行数
//"__VA_ARGS__" 处理可变参数的宏，但是当可变参数为空时，会出问题，一般使用"##__VA_ARGS__"

// 定义宏控制是否保存日志信息到日志文件中
#define SAVEFILE()        \
    do                    \
    {                     \
        Save_File = true; \
    } while (0)

#define SAVESCREEN()       \
    do                     \
    {                      \
        Save_File = false; \
    } while (0)

    const std::string defaultpath="./temp/";//默认路径
    //路径拼接工具类
    class PathUtil
    {
    public:
        //构建传入的后缀，拼接路径
        static std::string AddSuffix(const std::string& filename,const std::string& suf)
        {
            std::string path_name=defaultpath;
            path_name+=filename;
            path_name+=suf;
            return path_name;
        } 

        //编译时需要的临时文件
        //构建完整源文件名，路径+文件名+后缀
        static std::string Source(const std::string& filename)
        {
            return AddSuffix(filename,".cpp");
        }
        //构建完整可执行程序，路径+后缀
        static std::string Exe(const std::string& filename)
        {
            return AddSuffix(filename,".exe");
        }
        //构建程序编译时对应的标准错误，路径+后缀
        static std::string CompileError(const std::string& filename)
        {
            return AddSuffix(filename,".compile");
        }

        //运行时需要的临时文件
        //构建标准输入文件
        static std::string StdIn(const std::string& filename)
        {
            return AddSuffix(filename,".stdin");
        }
        //构建标准输出文件
        static std::string StdOut(const std::string& filename)
        {
            return AddSuffix(filename,".stdout");
        }
        //构建程序运行时对应的标准错误，路径+后缀
        static std::string StdError(const std::string& filename)
        {
            return AddSuffix(filename,".stderr");
        }
    };

    class TimeUtil
    {
    public:
        //获取毫秒级时间戳
        static std::string GetTimeMs()
        {
            struct timeval t;
            gettimeofday(&t,nullptr);
            return std::to_string(t.tv_sec*1000+t.tv_usec/1000);
        }
    };

    //文件相关操作
    class FileUtil
    {
    public:
        //判断文件是否存在
        static bool IsFileExists(const std::string& pathname)
        {
            struct stat st;
            //int stat(const char *__restrict__ __file, stat *__restrict__ __buf)
            //获取文件属性到__buf中
            //成功返回0，失败返回-1
            int ret=stat(pathname.c_str(),&st);
            if(ret==0)
            {
                return true;
            }
            return false;
        }

        //生成唯一的随机文件名(没有路径和后缀)
        static std::string UniqueFileName()
        {
            //通过毫秒级时间戳和一个原子性递增的静态变量，保证唯一性
            static std::atomic<int> id(0);//一个原子性递增的静态值
            id++;

            std::string ms=TimeUtil::GetTimeMs();
            std::string ID=std::to_string(id);
            std::string unique_name=ms+"_"+ID;

            return unique_name;
        }

        //把code中的内容写入到filename文件中
        static bool WriteFile(const std::string& filename,const std::string& content)
        {
            std::ofstream out(filename);
            if(!out.is_open())
            {
                return false;
            }
            out.write(content.c_str(),content.size());
            out.close();
            return true;
        }

        //从文件中读取数据
        static bool ReadFile(const std::string& filename,std::string& content,const bool flag=false)
        {
            content.clear();//清空数据

            std::ifstream in(filename);
            if(!in.is_open())
            {
                return false;
            }
            std::string line;
            //getline默认不保存换行符'\n'
            while(std::getline(in,line))
            {
                content+=line;
                if(flag)
                {
                    content+='\n';
                }
            }
            in.close();
            return true;
        }
    };

    //字符串操作
    class StringUtil
    {
    public:
        //切分字符串
        //把src字符串以sep为分隔符进行切分后的子字符串存进res中
        static int SplitString(const std::string& src,std::vector<std::string>& res,const std::string& sep)
        {
            // size_t pos=0,index=0;
            // while(index<src.size())
            // {
            //     pos=src.find(sep,index);
            //     if(pos==std::string::npos)//找到最后一个
            //     {
            //         res.emplace_back(src.substr(index));
            //         break;
            //     }
            //     if(pos==index)//出现连续的分隔符
            //     {
            //         index+=sep.size();
            //         continue;
            //     }
            //     res.emplace_back(src.substr(index,pos-index));
            //     index=pos+sep.size();
            // }

            //借助boost库split函数实现字符串分割
            //boost::algorithm::token_compress_on：出现多个连续分隔符时不保留空串
            //boost::algorithm::token_compress_off：出现多个连续分隔符时保留空串
            boost::split(res,src,boost::is_any_of(sep),boost::algorithm::token_compress_on);
            return res.size();
        } 
    };
}
